package com.waymap.utils;

import com.waymap.domain.ItemInventorys;
import com.waymap.domain.Items;
import com.waymap.domain.NSOperateData;
import com.waymap.mapper.ItemInventorysMapper;
import com.waymap.mapper.ItemsMapper;
import com.waymap.mapper.NSOperateDataMapper;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional;
import java.util.Timer;
import java.util.TimerTask;

@Component
public class SyncInvertoryService {
    @Resource
    private ItemsMapper itemsMapper;
    @Resource
    private ItemInventorysMapper itemInventorysMapper;
    @Resource
    private NSOperateDataMapper nsOperateDataMapper;

    /**
     * by  alfred
     *
     * @param location  仓库id
     * @param itemId    产品id
     * @param accountId 客户账号id
     * @param binName   库位名，开了库位的产品必须填库位，不开库位的则该值为空
     * @param lotNumber 批次号，批次产品须填，非批次产品该值为空
     *                  更新WMS库存数据，根据产品的类型
     *                  L为批次不开库位的产品
     *                  IB为开库位非批次产品
     *                  IB为开库位非批次产品
     *                  LB为开库位的批次产品
     */

    public Optional<ItemInventorys> findItemInventory(int location, int itemId, String accountId, String binName, String lotNumber) {
        Items item = new Items();
        item.setAccountId(accountId);
        item.setItemId(itemId);
        item = itemsMapper.selectOne(item);
        ItemInventorys iinv = new ItemInventorys();
        iinv.setAccountId(accountId);
        iinv.setItemId(itemId);
        iinv.setLocationId(location);
        if ("L".equals(item.getItemType())) {
            iinv.setLotNumber(lotNumber);
        } else if ("LB".equals(item.getItemType())) {
            iinv.setLotNumber(lotNumber);
            iinv.setBinName(binName);
        } else if ("IB".equals(item.getItemType())) {
            iinv.setBinName(binName);
        }
        return Optional.ofNullable(itemInventorysMapper.selectOne(iinv));
    }


    /**
     * by  alfred
     * 修改库存
     *
     * @param inventoryId itemInventory id
     * @param qty         数量，出库时为负数，入库时为正数
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateItemInventory(int inventoryId, int qty) {
        ItemInventorys binVo = new ItemInventorys();
        binVo.setId(inventoryId);
        binVo.setQuantityAvailable(qty);
        itemInventorysMapper.updateQuantityAvailableById(binVo);
    }

    /**
     * by  alfred
     * 新增库存
     *
     * @param itemId    产品id
     * @param accountId 客户账号id
     * @param binId     库位ID
     * @param binName   库位名，开了库位的产品必须填库位，不开库位的则该值为空
     * @param lotNumber 批次号，批次产品须填，非批次产品该值为空
     * @param qty       数量，出库时为负数，入库时为正数
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertItemInventory(int location, int itemId, String accountId, int binId, String binName, String lotNumber, int qty) {
        ItemInventorys o = new ItemInventorys();
        o.setItemId(itemId);
        o.setLocationId(location);
        o.setAccountId(accountId);
        o.setBinName(binName);
        o.setLotNumber(lotNumber);
        o.setBinId(binId);
        o.setQuantityAvailable(qty);
        itemInventorysMapper.insert(o);
    }

    /**
     * by  alfred
     * 箱体转移
     *
     * @param jsonArray
     */
    @Transactional(rollbackFor = Exception.class)
    public void binTransfer(JSONArray jsonArray, String syncType, String type, String tranid) {
        for (int i = 0; i < jsonArray.size(); i++) {
            net.sf.json.JSONObject jsonObject = jsonArray.getJSONObject(i);
            Integer quantity = Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", ""));
            Optional<ItemInventorys> itemInventory = findItemInventory(Integer.parseInt(jsonObject.getString("location")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("binnumber"),
                    (String) jsonObject.get("lotNumber"));
            if (itemInventory.isPresent()) {
                updateItemInventory(itemInventory.get().getId(), itemInventory.get().getQuantityAvailable() - quantity);
            }
            Optional<ItemInventorys> toItemInventory = findItemInventory(Integer.parseInt(jsonObject.getString("location")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("tobinnumber"),
                    (String) jsonObject.get("lotNumber"));
            if (toItemInventory.isPresent()) {
                updateItemInventory(toItemInventory.get().getId(), toItemInventory.get().getQuantityAvailable() + quantity);
            } else {
                insertItemInventory(
                        Integer.parseInt((String) jsonObject.get("location")),
                        Integer.valueOf(jsonObject.get("itemId").toString()),
                        (String) jsonObject.get("accountId"),
                        Integer.parseInt(jsonObject.get("tobinnumberId").toString()),
                        (String) jsonObject.get("tobinnumber"), (String) jsonObject.get("lotNumber"),
                        Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", "")));
            }

            Date date = new Date();
            NSOperateData nsOperateData = new NSOperateData();
            nsOperateData.setAccountId((String) jsonObject.get("accountId"));
            nsOperateData.setType(syncType);
            nsOperateData.setTranid(tranid);
            nsOperateData.setOperate(type);
            nsOperateData.setItem((String) jsonObject.get("itemName"));
            nsOperateData.setItemId(Integer.valueOf(jsonObject.get("itemId").toString()));
            //nsOperateData.setLotNumber((String) jsonObject.get("lotNumber"));
            nsOperateData.setBinName((String) jsonObject.get("binnumber"));
            nsOperateData.setLocation(Integer.valueOf(jsonObject.get("location").toString()));
            nsOperateData.setLocationName((String) jsonObject.get("locationName"));
            nsOperateData.setQuantity(0-quantity);
            nsOperateData.setCreationDate(date);
            nsOperateDataMapper.insert(nsOperateData);

            NSOperateData nsOperateData1 = new NSOperateData();
            nsOperateData1.setAccountId((String) jsonObject.get("accountId"));
            nsOperateData1.setType(syncType);
            nsOperateData1.setTranid(tranid);
            nsOperateData1.setOperate(type);
            nsOperateData1.setItem((String) jsonObject.get("itemName"));
            nsOperateData1.setItemId(Integer.valueOf(jsonObject.get("itemId").toString()));
            //nsOperateData.setLotNumber((String) jsonObject.get("lotNumber"));
            nsOperateData1.setBinName((String) jsonObject.get("tobinnumber"));
            nsOperateData1.setLocation(Integer.valueOf(jsonObject.get("location").toString()));
            nsOperateData1.setLocationName((String) jsonObject.get("locationName"));
            nsOperateData1.setQuantity(quantity);
            nsOperateData1.setCreationDate(date);
            nsOperateDataMapper.insert(nsOperateData1);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void inventoryTransfer(JSONArray jsonArray, String syncType, String type, String tranid) {
        for (int i = 0; i < jsonArray.size(); i++) {
            net.sf.json.JSONObject jsonObject = jsonArray.getJSONObject(i);
            Integer quantity = Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", ""));
            Optional<ItemInventorys> itemInventory = findItemInventory(Integer.parseInt(jsonObject.getString("location")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("binnumber"),
                    (String) jsonObject.get("lotNumber"));
            if (itemInventory.isPresent()) {
                updateItemInventory(itemInventory.get().getId(), itemInventory.get().getQuantityAvailable() - quantity);
            }
            Optional<ItemInventorys> toItemInventory = findItemInventory(Integer.parseInt(jsonObject.getString("tolocation")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("tobinnumber"),
                    (String) jsonObject.get("lotNumber"));
            if (toItemInventory.isPresent()) {
                updateItemInventory(toItemInventory.get().getId(), toItemInventory.get().getQuantityAvailable() + quantity);
            } else {
                insertItemInventory(
                        Integer.parseInt((String) jsonObject.get("tolocation")),
                        Integer.valueOf(jsonObject.get("itemId").toString()),
                        (String) jsonObject.get("accountId"),
                        Integer.parseInt(jsonObject.get("tobinnumberId").toString()),
                        (String) jsonObject.get("tobinnumber"), (String) jsonObject.get("lotNumber"),
                        Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", "")));
            }

            NSOperateData nsOperateData = new NSOperateData();
            nsOperateData.setAccountId((String) jsonObject.get("accountId"));
            nsOperateData.setType(syncType);
            nsOperateData.setTranid(tranid);
            nsOperateData.setOperate(type);
            nsOperateData.setItem((String) jsonObject.get("itemName"));
            nsOperateData.setItemId(Integer.valueOf(jsonObject.get("itemId").toString()));
            //nsOperateData.setLotNumber((String) jsonObject.get("lotNumber"));
            nsOperateData.setBinName((String) jsonObject.get("binnumber"));
            nsOperateData.setToBinName((String) jsonObject.get("tobinnumber"));
            nsOperateData.setLocation(Integer.valueOf(jsonObject.get("location").toString()));
            nsOperateData.setLocationName((String) jsonObject.get("locationName"));
            nsOperateData.setQuantity(quantity);
            nsOperateDataMapper.insert(nsOperateData);
        }
    }

    /**
     * by  alfred
     * 库存调整
     *
     * @param jsonArray
     * @param type  判断操作类型（create delete）
     */
    @Transactional(rollbackFor = Exception.class)
    public void adjustInventory(JSONArray jsonArray, String syncType, String type, String tranid) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Optional<ItemInventorys> itemInventorys = findItemInventory(
                    Integer.parseInt(jsonObject.getString("location")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("binName"),
                    (String) jsonObject.get("lotNumber"));
            Integer quantity = Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", ""));
            if (itemInventorys.isPresent()) {
                int qty = 0;
                if (type.equals("delete")) {
                    qty = itemInventorys.get().getQuantityAvailable() - quantity;
                } else {
                    qty = itemInventorys.get().getQuantityAvailable() + quantity;
                }
                updateItemInventory(itemInventorys.get().getId(), qty);
            } else {
                insertItemInventory(Integer.parseInt((String) jsonObject.get("location")),
                        Integer.valueOf(jsonObject.get("itemId").toString()),
                        (String) jsonObject.get("accountId"),
                        Integer.parseInt(Optional.of((String) jsonObject.get("binnumber")).orElse("0")),
                        (String) jsonObject.get("binName"),
                        (String) jsonObject.get("lotNumber"),
                        quantity
                );
            }

            NSOperateData nsOperateData = new NSOperateData();
            nsOperateData.setAccountId((String) jsonObject.get("accountId"));
            nsOperateData.setType(syncType);
            nsOperateData.setTranid(tranid);
            nsOperateData.setOperate(type);
            nsOperateData.setItem((String) jsonObject.get("itemName"));
            nsOperateData.setItemId(Integer.valueOf(jsonObject.get("itemId").toString()));
            //nsOperateData.setLotNumber((String) jsonObject.get("lotNumber"));
            nsOperateData.setBinName((String) jsonObject.get("binName"));
            nsOperateData.setLocation(Integer.valueOf(jsonObject.get("location").toString()));
            nsOperateData.setLocationName((String) jsonObject.get("locationName"));
            nsOperateData.setQuantity(quantity);
            nsOperateDataMapper.insert(nsOperateData);
        }
    }

    /**
     * by  alfred
     * itemReceipt
     *
     * @param jsonArray
     * @param type  判断操作类型（create delete）
     */
    @Transactional(rollbackFor = Exception.class)
    public void itemReceipt(JSONArray jsonArray, String syncType, String type, String tranid) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Optional<ItemInventorys> itemInventorys = findItemInventory(
                    Integer.parseInt(jsonObject.getString("location")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("binName"),
                    (String) jsonObject.get("lotNumber"));
            Integer quantity = Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", ""));
            if (itemInventorys.isPresent()) {
                int qty = 0;
                if (type.equals("delete")) {
                    qty = itemInventorys.get().getQuantityAvailable() - quantity;
                } else {
                    qty = itemInventorys.get().getQuantityAvailable() + quantity;
                }
                updateItemInventory(itemInventorys.get().getId(), qty);
            } else {
                insertItemInventory(Integer.parseInt((String) jsonObject.get("location")),
                        Integer.valueOf(jsonObject.get("itemId").toString()),
                        (String) jsonObject.get("accountId"),
                        Integer.parseInt(Optional.of((String) jsonObject.get("binnumber")).orElse("0")),
                        (String) jsonObject.get("binName"),
                        (String) jsonObject.get("lotNumber"),
                        quantity
                );
            }

            NSOperateData nsOperateData = new NSOperateData();
            nsOperateData.setAccountId((String) jsonObject.get("accountId"));
            nsOperateData.setType(syncType);
            nsOperateData.setTranid(tranid);
            nsOperateData.setOperate(type);
            nsOperateData.setItem((String) jsonObject.get("itemName"));
            nsOperateData.setItemId(Integer.valueOf(jsonObject.get("itemId").toString()));
            //nsOperateData.setLotNumber((String) jsonObject.get("lotNumber"));
            nsOperateData.setBinName((String) jsonObject.get("binName"));
            nsOperateData.setLocation(Integer.valueOf(jsonObject.get("location").toString()));
            nsOperateData.setLocationName((String) jsonObject.get("locationName"));
            nsOperateData.setQuantity(quantity);
            nsOperateDataMapper.insert(nsOperateData);
        }
    }

    /**
     * by  alfred
     * itemFulfill
     *
     * @param jsonArray
     * @param type  判断操作类型（create delete）
     */
    @Transactional(rollbackFor = Exception.class)
    public void itemFulfill(JSONArray jsonArray, String syncType, String type, String tranid) {
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Optional<ItemInventorys> itemInventorys = findItemInventory(
                    Integer.parseInt(jsonObject.getString("location")),
                    Integer.parseInt(jsonObject.getString("itemId")),
                    (String) jsonObject.get("accountId"),
                    (String) jsonObject.get("binName"),
                    (String) jsonObject.get("lotNumber"));
            Integer quantity = Integer.parseInt(StringUtils.substringBefore(jsonObject.get("quantity").toString(), ".").replaceAll(" ", ""));
            if (itemInventorys.isPresent()) {
                int qty = 0;
                if (type.equals("delete")) {
                    qty = itemInventorys.get().getQuantityAvailable() + quantity;
                } else {
                    qty = itemInventorys.get().getQuantityAvailable() - quantity;
                }
                updateItemInventory(itemInventorys.get().getId(), qty);
            }

            NSOperateData nsOperateData = new NSOperateData();
            nsOperateData.setAccountId((String) jsonObject.get("accountId"));
            nsOperateData.setType(syncType);
            nsOperateData.setTranid(tranid);
            nsOperateData.setOperate(type);
            nsOperateData.setItem((String) jsonObject.get("itemName"));
            nsOperateData.setItemId(Integer.valueOf(jsonObject.get("itemId").toString()));
            //nsOperateData.setLotNumber((String) jsonObject.get("lotNumber"));
            nsOperateData.setBinName((String) jsonObject.get("binName"));
            nsOperateData.setLocation(Integer.valueOf(jsonObject.get("location").toString()));
            nsOperateData.setLocationName((String) jsonObject.get("locationName"));
            nsOperateData.setQuantity(quantity);
            nsOperateDataMapper.insert(nsOperateData);
        }

    }


}
